// (C) 2022 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.

interface i3c_phy_mgmt_if (
    input clk,
    input rstn
);
    import i3c_pkg::*;

    logic       busy;
    status_t    status;
    request_t   request;
    logic [7:0] wr_data;
    logic [7:0] rd_data;
    logic       rd_data_valid;

    `ifdef SIMULATION
        event status_changed;
        event status_single_start;
        event status_repeated_start;
        event status_stop;
        event status_transition_parity; 
        event status_transition_end; 
        event status_transition_end_with_repeated_start; 
        event status_transition_continue; 
        event status_ack; 
        event status_nack; 
        event status_address; 
        event status_address_last; 
        event status_data; 
        event status_data_last; 
        event status_idle; 
        event status_ibi_start;
        event status_ibi_address; 
        event status_ibi_address_last; 
    `endif

    modport master (
        input busy,
        input status,
        output request,
        output wr_data,
        input rd_data,
        input rd_data_valid
    );

    modport slave (
        output busy,
        output status,
        input request,
        input wr_data,
        output rd_data,
        output rd_data_valid
    );

    modport monitor (
        input busy,
        input status,
        input request,
        input wr_data,
        input rd_data,
        input rd_data_valid
    );

    `ifdef SIMULATION
        clocking cb_master @ (posedge clk);
            inout busy;
            inout status;
            input request;
            input wr_data;
            inout rd_data;
            inout rd_data_valid;
        endclocking

        modport cb_master_modport (
            input rstn,
            clocking cb_master
        );

        clocking cb_slave @ (posedge clk);
            input busy;
            input status;
            inout request;
            inout wr_data;
            input rd_data;
            input rd_data_valid;
        endclocking

        modport cb_slave_modport (
            input rstn,
            clocking cb_slave
        );

        clocking cb_monitor @ (posedge clk);
            input busy;
            input status;
            input request;
            input wr_data;
            input rd_data;
            input rd_data_valid;
        endclocking

        modport cb_monitor_modport (
            input rstn,
            clocking cb_monitor
        );
    `endif

    `ifdef SIMULATION
        status_t status_before;

        initial begin
            status_before = STATUS_IDLE;

            forever begin
                @(posedge clk); 
                #1;
                if ((status === STATUS_SINGLE_START) & (status_before !== STATUS_SINGLE_START)) begin
                    ->status_changed;
                    ->status_single_start;
                end
                else if ((status === STATUS_REPEATED_START) & (status_before !== STATUS_REPEATED_START)) begin
                    ->status_changed;
                    ->status_repeated_start;
                end
                else if ((status === STATUS_STOP) & (status_before !== STATUS_STOP)) begin
                    ->status_changed;
                    ->status_stop;
                end
                else if ((status === STATUS_TRANSITION_PARITY) & (status_before !== STATUS_TRANSITION_PARITY)) begin
                    ->status_changed;
                    ->status_transition_parity;
                end
                else if ((status === STATUS_TRANSITION_END) & (status_before !== STATUS_TRANSITION_END)) begin
                    ->status_changed;
                    ->status_transition_end;
                end
                else if ((status === STATUS_TRANSITION_END_WITH_REPEATED_START) & (status_before !== STATUS_TRANSITION_END_WITH_REPEATED_START)) begin
                    ->status_changed;
                    ->status_transition_end_with_repeated_start;
                end
                else if ((status === STATUS_TRANSITION_CONTINUE) & (status_before !== STATUS_TRANSITION_CONTINUE)) begin
                    ->status_changed;
                    ->status_transition_continue;
                end
                else if ((status === STATUS_ACK) & (status_before !== STATUS_ACK)) begin
                    ->status_changed;
                    ->status_ack;
                end
                else if ((status === STATUS_NACK) & (status_before !== STATUS_NACK)) begin
                    ->status_changed;
                    ->status_nack;
                end
                else if ((status === STATUS_ADDRESS) & (status_before !== STATUS_ADDRESS)) begin
                    ->status_changed;
                    ->status_address;
                end
                else if ((status === STATUS_ADDRESS_LAST) & (status_before !== STATUS_ADDRESS_LAST)) begin
                    ->status_changed;
                    ->status_address_last;
                end
                else if ((status === STATUS_DATA) & (status_before !== STATUS_DATA)) begin
                    ->status_changed;
                    ->status_data;
                end
                else if ((status === STATUS_DATA_LAST) & (status_before !== STATUS_DATA_LAST)) begin
                    ->status_changed;
                    ->status_data_last;
                end
                else if ((status === STATUS_IDLE) & (status_before !== STATUS_IDLE)) begin
                    ->status_changed;
                    ->status_idle;
                end
                if ((status === STATUS_IBI_START) & (status_before !== STATUS_IBI_START)) begin
                    ->status_changed;
                    ->status_ibi_start;
                end
                else if ((status === STATUS_IBI_ADDRESS) & (status_before !== STATUS_IBI_ADDRESS)) begin
                    ->status_changed;
                    ->status_ibi_address;
                end
                else if ((status === STATUS_IBI_ADDRESS_LAST) & (status_before !== STATUS_IBI_ADDRESS_LAST)) begin
                    ->status_changed;
                    ->status_ibi_address_last;
                end

                status_before = status;
            end
        end
    `endif     

endinterface